-- 特别说明:代码注释是ChatGPT5生成的,不要无脑相信
---------------------------------------------------------------------------
-- 自定义白雾（瘴气）云：bboy_miasma_cloud
-- 结构与官方 miasma_cloud 基本一致，但纹理、网络字段名等做了自定义前缀
-- 主要包含两部分：
--   1) 服务端实体（判定玩家是否处于雾内、与火的交互、维护观察者列表）
--   2) 客户端粒子 FX 容器（真正渲染烟雾与火星）
---------------------------------------------------------------------------

-- 自定义纹理（这里使用了 resolvefilepath 以确保从 mod 目录解析）
local ANIM_SMOKE_TEXTURE         = resolvefilepath("fx/miasma_white.tex")
-- 烟雾使用的通用粒子着色器（透明混合）
local SMOKE_SHADER               = "shaders/vfx_particle.ksh"

-- 颜色/缩放包络名（EnvelopeManager 的键）
local COLOUR_ENVELOPE_NAME_SMOKE = "miasma_cloud_colourenvelope_smoke"
local SCALE_ENVELOPE_NAME_SMOKE  = "miasma_cloud_scaleenvelope_smoke"

-- 火星（余烬）纹理与着色器
local EMBER_TEXTURE              = "fx/snow.tex"
local EMBER_SHADER               = "shaders/vfx_particle_add.ksh"

local COLOUR_ENVELOPE_NAME_EMBER = "miasma_cloud_colourenvelope_ember"
local SCALE_ENVELOPE_NAME_EMBER  = "miasma_cloud_scaleenvelope_ember"

-- 需要的预制体（客户端局部 FX 实体）
local prefabs                    =
{
    "miasmadebuff",         --（若使用到瘴气相关 debuff，可保留；未使用可移除）
    "bboy_miasma_cloud_fx", -- 客户端粒子 FX 容器
}

-- 客户端粒子 FX 所需资源（注意：Asset("IMAGE", ...) 指向 .tex）
local assets_fx                  =
{
    Asset("IMAGE", ANIM_SMOKE_TEXTURE), -- 白雾贴图
    Asset("IMAGE", EMBER_TEXTURE),      -- 火星贴图
    Asset("SHADER", SMOKE_SHADER),      -- 渲染烟雾的 shader
    Asset("SHADER", EMBER_SHADER),      -- 渲染火星的 shader（加色混合）
}

---------------------------------------------------------------------------
-- 粒子参数：尺寸、寿命等
---------------------------------------------------------------------------

local SMOKE_SIZE                 = 0.8  -- 烟雾单片缩放基准
local SMOKE_MAX_LIFETIME         = 5.0 -- 烟雾粒子最大生存时间（秒）
local FIRE_DECAY_MULTIPLIER      = 0.25 -- 近火时烟雾寿命倍率（更快消散）
local EMBER_MAX_LIFETIME         = 1.5  -- 火星最大寿命（秒）

-- 遮罩/判定半径的计算（与官方一致）
-- 这里的“间距/半径”决定了云块的覆盖大小与视觉折叠
local MIASMA_SPACING_RADIUS      = SQRT2 * 1 * TILE_SCALE / 2
local MIASMA_PARTICLE_RADIUS     = MIASMA_SPACING_RADIUS / 2
local MIASMA_RADIUS              = math.ceil(MIASMA_SPACING_RADIUS)
local PLAY_RADIUS                = math.ceil(SQRT2 * 7 * TILE_SCALE / 2)
-- 渲染半径（略小于逻辑半径，让烟雾片不溢出太多）
local SMOKE_RADIUS               = MIASMA_RADIUS - SMOKE_SIZE * 1.3

---------------------------------------------------------------------------
-- 客户端/服务端 共享的全局状态（计数与朝向）
---------------------------------------------------------------------------

-- 服务端：当前世界中 bboy_miasma_cloud 的数量（供世界组件/优化用）
local _MiasmaCloudCount          = 0
local function GetMiasmaCloudCount(world)
    return _MiasmaCloudCount
end

-- 客户端：跟踪所有 miasma_cloud 实体（用于随相机朝向更新半圆粒子位置）
local _MiasmaCloudEntities = nil
local function OnRemove_Client(inst)
    _MiasmaCloudEntities[inst] = nil
end

-- 记录相机朝向与 sin/cos，避免每帧重复计算
local _OldHeading = nil
local _OldHeading_cos = nil
local _OldHeading_sin = nil

-- 当相机朝向改变时，更新每个云实例的“前/后半圆” FX 的偏移
local function OnCameraUpdate_Client(dt)
    local heading = TheCamera:GetHeading()
    if heading ~= _OldHeading then
        _OldHeading = heading
        _OldHeading_cos = math.cos(_OldHeading * DEGREES)
        _OldHeading_sin = math.sin(_OldHeading * DEGREES)
        local ox, oz = _OldHeading_cos * MIASMA_PARTICLE_RADIUS,
            _OldHeading_sin * MIASMA_PARTICLE_RADIUS
        for miasmacloud, _ in pairs(_MiasmaCloudEntities) do
            miasmacloud._front_cloud_fx.Transform:SetPosition(ox, 0, oz)
            miasmacloud._back_cloud_fx.Transform:SetPosition(-ox, 0, -oz)
        end
    end
end

-- 只更新某个云实例（用于创建时立即同步）
local function OnCameraUpdate_Targeted_Client(miasmacloud)
    local heading = TheCamera:GetHeading()
    if heading ~= _OldHeading then
        _OldHeading = heading
        _OldHeading_cos = math.cos(_OldHeading * DEGREES)
        _OldHeading_sin = math.sin(_OldHeading * DEGREES)
    end
    local ox, oz = _OldHeading_cos * MIASMA_PARTICLE_RADIUS,
        _OldHeading_sin * MIASMA_PARTICLE_RADIUS
    miasmacloud._front_cloud_fx.Transform:SetPosition(ox, 0, oz)
    miasmacloud._back_cloud_fx.Transform:SetPosition(-ox, 0, -oz)
end

---------------------------------------------------------------------------
-- 包络（Envelope）：控制粒子的颜色/缩放随时间的变化曲线
---------------------------------------------------------------------------

local function IntColour(r, g, b, a)
    return { r / 255, g / 255, b / 255, a / 255 }
end

local function InitEnvelope()
    -- 烟雾颜色：0→透明，0.1~0.9→不透明白色，1→透明
    EnvelopeManager:AddColourEnvelope(
        COLOUR_ENVELOPE_NAME_SMOKE,
        {
            { 0,  IntColour(255, 255, 255, 0) },
            { .1, IntColour(255, 255, 255, 255) },
            { .2, IntColour(255, 255, 255, 255) },
            { .3,  IntColour(255, 255, 255, 0) },
        }
    )

    -- 烟雾缩放：从 1.0 略微缩到 0.8（给点动态）
    local smoke_max_scale = SMOKE_SIZE
    EnvelopeManager:AddVector2Envelope(
        SCALE_ENVELOPE_NAME_SMOKE,
        {
            { 0, { smoke_max_scale, smoke_max_scale } },
            { 1, { smoke_max_scale * 0.8, smoke_max_scale * 0.8 } },
        }
    )

    -- 火星颜色：暖色加色，头中段更亮，尾段透明
    EnvelopeManager:AddColourEnvelope(
        COLOUR_ENVELOPE_NAME_EMBER,
        {
            { 0,  IntColour(200, 85, 60, 25) },
            { .2, IntColour(230, 140, 90, 200) },
            { .3, IntColour(255, 90, 70, 255) },
            { .6, IntColour(255, 90, 70, 255) },
            { .9, IntColour(255, 90, 70, 230) },
            { 1,  IntColour(255, 70, 70, 0) },
        }
    )

    -- 火星缩放：从 0.7 → 0.56 → 0.07
    local ember_max_scale = 0.7
    EnvelopeManager:AddVector2Envelope(
        SCALE_ENVELOPE_NAME_EMBER,
        {
            { 0,   { ember_max_scale, ember_max_scale } },
            { 0.5, { ember_max_scale * 0.8, ember_max_scale * 0.8 } },
            { 1,   { ember_max_scale * 0.1, ember_max_scale * 0.1 } },
        }
    )

    -- 释放局部函数引用，加快 GC
    InitEnvelope = nil
    IntColour    = nil
end

---------------------------------------------------------------------------
-- 发射逻辑（粒子生成）
---------------------------------------------------------------------------

-- 半径限制（用于近/远 culling）
local RADIUS_SQ_DENY  = 4 * 4
local RADIUS_SQ_ALLOW = 40 * 40

-- 生成一颗火星（第二个 emitter：index=1）
-- 注意：这里被烟雾发射函数间接调用（当 isdiminishing=真）
local function emit_ember_fn(effect, ember_sphere_emitter, px, py, pz, vx, vy, vz)
    local ox, oy, oz = ember_sphere_emitter() -- 相对位移
    local ovx, ovy, ovz = .06 * UnitRand(), 0.2 + 0.3 * math.random(), .06 * UnitRand()

    effect:AddParticle(
        1,                                                -- emitter 索引
        EMBER_MAX_LIFETIME * (math.random() * 0.5 + 0.5), -- 寿命
        px + ox, 0 - oy, pz + oz,                         -- 初始位置（注意这里 y 为负 oy，效果向上飘）
        vx + ovx, vy + ovy, vz + ovz                      -- 初始速度
    )
end

-- 核心：生成一张烟雾片（第一个 emitter：index=0）
-- 会根据 isfront（半圆正/反）、相机朝向、与玩家距离等进行剔除与定位
local function emit_smoke_fn(effect, smoke_circle_emitter, ember_sphere_emitter, px, pz, ex, ez, isdiminishing, isfront, _world, _sim)
    -- 从圆上取一点（偏移）
    local ox, oz = smoke_circle_emitter()

    -- 将圆“折叠”为半圆（沿相机前后分两组半圆，减少穿插）
    if isfront then
        if ox < 0 then ox = -ox end
        ox = ox - MIASMA_PARTICLE_RADIUS
    else
        if ox > 0 then ox = -ox end
        ox = ox + MIASMA_PARTICLE_RADIUS
    end

    -- 按相机朝向旋转该点，使“前/后半圆”总是相对摄像机朝向分布
    if _OldHeading then
        ox, oz = ox * _OldHeading_cos - oz * _OldHeading_sin,
            ox * _OldHeading_sin + oz * _OldHeading_cos
    end

    -- 转为世界坐标（以瘴气实体为中心）
    ex, ez = ex + oz, ez + oz

    -- 与玩家的距离裁剪（太远就不发）
    local dx, dz = px - ex, pz - ez
    local dsq = dx * dx + dz * dz
    if dsq > RADIUS_SQ_ALLOW then
        return
    end

    -- 漫游区或虚空上不显示
    if not _world.Map:IsVisualGroundAtPoint(ex, 0, ez) then
        return
    end

    -- 初速度/寿命
    local vx, vy, vz = .01 * UnitRand(), 0.005 * UnitRand(), .01 * UnitRand()
    local lifetime = SMOKE_MAX_LIFETIME
    local oy = 0.5 * (1 + math.random())

    -- 若瘴气处于“消退状态”（靠近火），偶尔发火星；且烟雾更快上飘、寿命更短
    if isdiminishing then
        for i = 1, 8 do
            emit_ember_fn(effect, ember_sphere_emitter, ox, oy, oz, vx, vy, vz)
        end
        if math.random() < 0.75 then
            return
        end
        lifetime = lifetime * FIRE_DECAY_MULTIPLIER
        vy = vy + 0.3
    end

    -- 烟雾使用两帧 UV（0/0.5），随机切换避免图案同步
    local uv_offset = math.random(0, 1) * 0.5

    effect:AddRotatingParticleUV(
        0,                   -- emitter 索引（烟雾）
        lifetime,            -- 寿命
        ox, oy, oz,          -- 初始位置（相对 FX 容器）
        vx, vy, vz,          -- 初始速度
        math.random() * 360, -- 初始角度
        UnitRand() * 0.1,    -- 角速度
        uv_offset, 0         -- UV 起始
    )
end

---------------------------------------------------------------------------
-- 客户端 FX 容器：配置 emitters 并注册帧回调以持续发射
---------------------------------------------------------------------------

local function SetupParticles(inst)
    if InitEnvelope ~= nil then
        InitEnvelope()
    end

    -- 该实体不带 AnimState，而是直接创建 VFXEffect（粒子系统）
    local effect = inst.entity:AddVFXEffect()
    effect:InitEmitters(2) -- 0:烟雾  1:火星

    -- Emitter 0：烟雾
    effect:SetRenderResources(0, ANIM_SMOKE_TEXTURE, SMOKE_SHADER)
    effect:SetMaxNumParticles(0, 50)             -- 上限（越大越密）
    effect:SetRotationStatus(0, true)            -- 粒子允许旋转
    effect:SetMaxLifetime(0, SMOKE_MAX_LIFETIME) -- 最大寿命
    effect:SetColourEnvelope(0, COLOUR_ENVELOPE_NAME_SMOKE)
    effect:SetScaleEnvelope(0, SCALE_ENVELOPE_NAME_SMOKE)
    effect:SetUVFrameSize(0, 0.5, 1)               -- 两帧横向动画（0~0.5 与 0.5~1）
    effect:SetBlendMode(0, BLENDMODE.AlphaBlended) -- 透明混合
    effect:SetSortOrder(0, 0)
    effect:SetSortOffset(0, 0)
    effect:SetRadius(0, SMOKE_RADIUS)
    effect:SetDragCoefficient(0, .1) -- 阻尼（越大越“黏”）

    -- Emitter 1：火星（加色混合，带辉光）
    effect:SetRenderResources(1, EMBER_TEXTURE, EMBER_SHADER)
    effect:SetMaxNumParticles(1, 128)
    effect:SetMaxLifetime(1, EMBER_MAX_LIFETIME)
    effect:SetColourEnvelope(1, COLOUR_ENVELOPE_NAME_EMBER)
    effect:SetScaleEnvelope(1, SCALE_ENVELOPE_NAME_EMBER)
    effect:SetBlendMode(1, BLENDMODE.Additive)
    effect:EnableBloomPass(1, true)
    effect:SetSortOrder(1, 0)
    effect:SetSortOffset(1, 0)
    effect:SetDragCoefficient(1, 0.07)

    -- 发射器帧更新：每 tick 累计一个“应发数量”，达到 1 就发一片烟雾（平滑发射率）
    local _world               = TheWorld
    local _sim                 = TheSim
    local smoke_circle_emitter = CreateCircleEmitter(SMOKE_RADIUS)
    local ember_sphere_emitter = CreateSphereEmitter(SMOKE_SIZE)
    local particles_per_tick   = 2 * TheSim:GetTickTime() -- 每帧 8 * dt（大约等效每秒固定速率）
    local num_to_emit          = 0

    EmitterManager:AddEmitter(inst, nil, function()
        local _player = ThePlayer
        if _player then
            -- FX 容器被 parent 到服务端实体（bboy_miasma_cloud）上
            local parent = inst.entity:GetParent()
            if parent and (parent.IsCloudEnabled == nil or parent:IsCloudEnabled()) then
                local px, _, pz     = _player.Transform:GetWorldPosition()
                local ex, _, ez     = parent.Transform:GetWorldPosition()
                local isdiminishing = parent._diminishing:value() -- 近火衰减标记（来自网络变量）
                local isfront       = inst._frontsemicircle       -- 该 FX 是“前半圆”还是“后半圆”

                num_to_emit         = num_to_emit + particles_per_tick
                while num_to_emit > 1 do
                    emit_smoke_fn(effect, smoke_circle_emitter, ember_sphere_emitter,
                        px, pz, ex, ez, isdiminishing, isfront, _world, _sim)
                    num_to_emit = num_to_emit - 1
                end
            end
        end
    end)
end

---------------------------------------------------------------------------
-- 服务端逻辑：管理“雾内观察者”（用于给玩家加减效果等）、与火堆的交互
---------------------------------------------------------------------------

-- 为了跨云块平滑，周期取 0.5s（注意：玩家离开云后并不会立刻移除效果）
local PERIOD = .5

-- 寻找观察对象时忽略的标签
local NO_TAGS = { "playerghost", "ghost", "shadow", "shadowminion", "noauradamage", "FX", "INLIMBO", "notarget", "noattack", "flight", "invisible" }

-- 清空表同时从 watcher 的 miasmawatcher 组件移除“来源”
local function ClearWatcherTable(inst, tbl)
    for k in pairs(tbl) do
        tbl[k] = nil
        -- if k:IsValid() and k.components.miasmawatcher ~= nil then
        --     -- k.components.miasmawatcher:RemoveMiasmaSource(inst)
        --     k:RemoveDebuff("bboy_nether_buff")
        -- end
    end
end

-- 与火的交互：靠近火（Tag=fire）会让云处于“消退”状态
local FIRE_MUST_TAGS = { "fire" }
local FIRE_RADIUS = MIASMA_RADIUS + 1 -- 稍微比云半径大一点

-- 周期任务：刷新 watchers、根据附近火堆设置 _diminishing
local function OnUpdate(inst)
    -- 三表轮换：watchers（当前）、watchers_exiting（即将离开）、watchers_toremove（上轮未清）
    local temp = inst.watchers_toremove
    inst.watchers_toremove = inst.watchers_exiting
    inst.watchers_exiting = inst.watchers
    inst.watchers = temp

    local x, y, z = inst.Transform:GetWorldPosition()

    -- 扫描半径内的实体，把有 miasmawatcher 组件的加入 watchers
    -- for i, v in ipairs(TheSim:FindEntities(x, y, z, MIASMA_RADIUS, nil, NO_TAGS)) do
    --     if v.entity:IsVisible() then
    --         if v.components.miasmawatcher ~= nil then
    --             inst.watchers[v] = true
    --             if inst.watchers_toremove[v] then
    --                 inst.watchers_toremove[v] = nil
    --             elseif inst.watchers_exiting[v] then
    --                 inst.watchers_exiting[v] = nil
    --             else
    --                 -- 第一次进入：通知 watcher“新增雾源”
    --                 -- v.components.miasmawatcher:AddMiasmaSource(inst)
    --                 v:AddDebuff("bboy_nether_buff", "bboy_nether_buff")
    --             end
    --         end
    --     end
    -- end

    -- 近火检查：设置“消退”网络变量；若未纳入 manager 管理，则用自杀任务模拟消退结束
    -- local miasmamanager = TheWorld.components.miasmamanager
    -- local nearestfire = TheSim:FindEntities(x, y, z, FIRE_RADIUS, FIRE_MUST_TAGS)[1]

    -- if nearestfire then
    --     if miasmamanager and miasmamanager:GetMiasmaAtPoint(x, y, z) then
    --         miasmamanager:SetMiasmaDiminishingAtPoint(x, y, z, true)
    --     elseif inst._miasma_kill_task == nil then
    --         -- 没有 manager 管理时，定时移除，模拟“被火驱散”
    --         inst._miasma_kill_task = inst:DoTaskInTime(
    --             TUNING.MIASMA_DIMINISH_INTERVAL_SECONDS * TUNING.MIASMA_MAXSTRENGTH,
    --             inst.Remove
    --         )
    --     end
    --     inst._diminishing:set(true)
    -- else
    --     if miasmamanager and miasmamanager:GetMiasmaAtPoint(x, y, z) then
    --         miasmamanager:SetMiasmaDiminishingAtPoint(x, y, z, false)
    --     elseif inst._miasma_kill_task ~= nil then
    --         inst._miasma_kill_task:Cancel()
    --         inst._miasma_kill_task = nil
    --     end
    --     inst._diminishing:set(false)
    -- end

    -- 从即将移除表中，统一做“离开云”的移除
    inst:ClearWatcherTable(inst.watchers_toremove)
end

-- 启停周期任务（实体睡眠/唤醒时调用）
local function StartAllWatchers(inst)
    if inst.task == nil then
        inst.task = inst:DoPeriodicTask(PERIOD, OnUpdate, math.random() * .5)
    end
end

local function StopAllWatchers(inst)
    if inst.task ~= nil then
        inst.task:Cancel()
        inst.task = nil

        inst:ClearWatcherTable(inst.watchers)
        inst:ClearWatcherTable(inst.watchers_exiting)
        inst:ClearWatcherTable(inst.watchers_toremove)
    end
end

-- 移除时维护全局计数，并向世界广播“是否存在瘴气云”
local function OnRemoveEntity(inst)
    inst:StopAllWatchers()
    _MiasmaCloudCount = _MiasmaCloudCount - 1
    if _MiasmaCloudCount == 0 then
        TheWorld:PushEvent("miasmacloudexists", false)
    end
end

local function OnTick(inst)
    local x, y, z = inst.Transform:GetWorldPosition()
    local players = FindPlayersInRange(x, y, z, PLAY_RADIUS, true)
    for k, player in pairs(players) do
        player:AddDebuff("bboy_nether_buff", "bboy_nether_buff")
    end
end

-- 睡醒回调
local function OnEntityWake(inst)
    inst:StartAllWatchers()
    if inst.bboy_task == nil then
        inst.bboy_task = inst:DoPeriodicTask(5, OnTick, nil)
    end
end
local function OnEntitySleep(inst)
    inst:StopAllWatchers()
    if inst.bboy_task ~= nil then
        inst.bboy_task:Cancel()
        inst.bboy_task = nil
    end
end

---------------------------------------------------------------------------
-- 客户端：把两个“半圆 FX 容器”作为子实体挂到本体上，随相机转向切换前后
---------------------------------------------------------------------------

local function AttachParticles(inst)
    -- 前半圆
    local front = SpawnPrefab("bboy_miasma_cloud_fx")
    front.entity:SetParent(inst.entity)
    front.Transform:SetPosition(MIASMA_PARTICLE_RADIUS, 0, 0)
    front._frontsemicircle = true

    -- 后半圆
    local back = SpawnPrefab("bboy_miasma_cloud_fx")
    back.entity:SetParent(inst.entity)
    back.Transform:SetPosition(-MIASMA_PARTICLE_RADIUS, 0, 0)

    inst._front_cloud_fx = front
    inst._back_cloud_fx  = back
end

---------------------------------------------------------------------------
-- 服务端预制体：bboy_miasma_cloud（逻辑体，不渲染）
---------------------------------------------------------------------------

local function fn()
    local inst = CreateEntity()

    inst.entity:AddTransform()
    inst.entity:AddNetwork()

    inst:AddTag("FX")     -- 仅表现用，不参与战斗等
    inst:AddTag("miasma") -- 标记为瘴气云

    -- 网络变量：是否处于“消退”（靠近火）状态，客户端用于调整发射逻辑
    inst._diminishing = net_bool(inst.GUID, "bboy_miasma_cloud._diminishing", "diminishingdirty")

    -- 专用客户端：附加本地 FX
    if not TheNet:IsDedicated() then
        AttachParticles(inst)
        if _MiasmaCloudEntities == nil then
            _MiasmaCloudEntities = {}
            if TheCamera then
                -- 注册全局相机侦听：相机转向时调整所有云的前后半圆位置
                TheCamera:AddListener("MiasmaClouds", OnCameraUpdate_Client)
            end
        end
        if TheCamera then
            -- 创建当帧立即把本体对齐一次
            OnCameraUpdate_Targeted_Client(inst)
        end
        _MiasmaCloudEntities[inst] = true
        inst:ListenForEvent("onremove", OnRemove_Client)
    end

    inst.entity:SetPristine()

    if not TheWorld.ismastersim then
        return inst
    end

    -- 观察者集（三表轮换，避免分配/回收抖动）
    inst.watchers          = {}
    inst.watchers_exiting  = {}
    inst.watchers_toremove = {}

    -- 服务端生命周期/睡眠
    inst.OnEntityWake      = OnEntityWake
    inst.OnEntitySleep     = OnEntitySleep
    inst.OnRemoveEntity    = OnRemoveEntity
    inst.ClearWatcherTable = ClearWatcherTable
    inst.StartAllWatchers  = StartAllWatchers
    inst.StopAllWatchers   = StopAllWatchers

    -- 全局计数 & 世界事件
    _MiasmaCloudCount      = _MiasmaCloudCount + 1
    if _MiasmaCloudCount == 1 then
        TheWorld:PushEvent("miasmacloudexists", true)
    end
    -- 把获取接口挂在世界对象上（若尚未占用）
    if TheWorld.GetMiasmaCloudCount == nil then
        TheWorld.GetMiasmaCloudCount = GetMiasmaCloudCount
    end

    return inst
end

---------------------------------------------------------------------------
-- 客户端预制体：bboy_miasma_cloud_fx（纯 FX 容器，用 VFXEffect 渲染）
---------------------------------------------------------------------------

local function fn_fx()
    local inst = CreateEntity()

    inst.entity:AddTransform()

    inst:AddTag("FX")
    -- 非网络实体，始终唤醒（粒子渲染需要）
    inst.entity:SetCanSleep(false)
    inst.persists = false

    -- 初始化粒子系统（两个 emitter）
    SetupParticles(inst)

    return inst
end

---------------------------------------------------------------------------
-- 导出预制体
---------------------------------------------------------------------------

return Prefab("bboy_miasma_cloud", fn, nil, prefabs),
    Prefab("bboy_miasma_cloud_fx", fn_fx, assets_fx)
